import namespace from "../namespace";
import ArrayList from "../util/ArrayList";
import JOSNUtil from "../util/JSONUtil";
import extend from "lodash/extend";
export class Polygon extends namespace.VectorFigure {
  NAME = `${namespace.namespace}.shape.Polygon`;

  constructor(opt) {
    super();

    const { vertices, attr } = opt || { vertices: new ArrayList(), attr: {} };

    super.attr(extend({}, attr));
    this.minX = 0;
    this.minY = 0;
    this.maxX = 0;
    this.maxY = 0;

    //顶点
    this.vertices = new ArrayList();

    if (!vertices.isEmpty()) {
      vertices.each((i, p) =>
        this.addVertex(new namespace.geo.Point(p.x, p.y))
      );
      this.setPosition(this.getPosition());
    } else {
      if (this.vertices.getSize() === 0) {
        let w = this.width;
        let h = this.height;
        let pos = this.getPosition();
        this.addVertex(new namespace.geo.Point(0, 0));
        this.addVertex(new namespace.geo.Point(w, 0));
        this.addVertex(new namespace.geo.Point(w, h));
        this.setPosition(pos);
      }
    }

    // path string
    this.svgPathString = null;

    // 多边形选中交互策略
    this.installPolicy(new namespace.policy.figure.VertexSelectionPolicy());
  }

  addVertex(x, y) {
    this.vertices.add(new namespace.geo.Point(x, y));

    this.svgPathString = null;
    this.repaint();

    this.updateBoundingBox();

    // this.editPolicy.each(function (i, e) {
    //   if (e instanceof namespace.policy.figure.DragDropEditPolicy) {
    //     e.moved(_this.canvas, _this);
    //   }
    // });

    return this;
  }

  getVertices() {
    return this.vertices;
  }

  getVertex(index) {
    return this.vertices.get(index);
  }

  setVertex(index, x = 0, y = 0) {
    let vertex = this.vertices.get(index);

    if (vertex === null || (vertex.x === x && vertex.y === y)) {
      return this;
    }

    vertex.x = parseFloat(x);
    vertex.y = parseFloat(y);

    this.svgPathString = null;

    this.repaint();
    this.updateBoundingBox();

    this.policys.each((i, e) => {
      if (e instanceof namespace.policy.figure.DragDropPolicy) {
        e.move(this.canvas, this);
      }
    });
  }

  setDimension(w, h) {
    let oldWidth = this.width;
    let oldHeight = this.height;

    super.setDimension(w, h);

    let fracWidth = (1 / oldWidth) * this.width;
    let fracHeight = (1 / oldHeight) * this.height;

    let thisX = this.x;
    let thisY = this.y;

    this.vertices.each((i, e) => {
      let diffX = (e.getX() - thisX) * fracWidth;
      let diffY = (e.getY() - thisY) * fracHeight;
      e.setPosition(thisX + diffX, thisY + diffY);
    });

    this.svgPathString = null;

    this.repaint();

    return this;
  }

  setPosition(x, y) {
    if (x instanceof namespace.geo.Point) {
      y = x.y;
      x = x.x;
    }
    this.svgPathString = null;

    let dx = x - this.minX;
    let dy = y - this.minY;

    this.translate(dx, dy);

    this.x = x;
    this.y = y;

    return this;
  }

  translate(dx, dy) {
    // if (this.shape === null) {
    //   return;
    // }

    // const newMatrix = this.oMatrix.clone();
    // newMatrix.translate(dx, dy);

    // this.shape.transform(newMatrix);

    // console.log(newMatrix.x());

    this.vertices.each((i, e) => e.translate(dx, dy));
    this.svgPathString = null;
    this.updateBoundingBox();

    this.repaint();

    // 移动各个顶点
    this.policys.each((i, e) => {
      if (e instanceof namespace.policy.figure.DragDropPolicy) {
        e.move(this.canvas, this);
      }
    });
  }

  // 更新边界框
  updateBoundingBox() {
    if (this.vertices.isEmpty()) {
      this.minX = this.x;
      this.minY = this.y;
      this.maxX = this.x + this.width;
      this.maxY = this.y + this.height;
    } else {
      this.minX = this.x = Math.min(...this.vertices.asArray().map(n => n.x));
      this.minY = this.y = Math.min(...this.vertices.asArray().map(n => n.y));
      this.maxX = Math.max(...this.vertices.asArray().map(n => n.x));
      this.maxY = Math.max(...this.vertices.asArray().map(n => n.y));
      this.width = this.maxX - this.minX;
      this.height = this.maxY - this.minY;
    }
  }

  createShapeElement() {
    return this.canvas.paper.path("M0 0L10 10");
  }

  calculatePath() {
    let path = [];

    let length = this.vertices.getSize();
    let p = this.vertices.get(0);
    // 起点
    path.push("M", p.x, " ", p.y);

    // 途经点
    for (let i = 1; i < length; i++) {
      p = this.vertices.get(i);
      path.push("L", p.x, " ", p.y);
    }
    // 闭合
    path.push("Z");

    this.svgPathString = path.join("");
    return this;
  }

  repaint(attributes = {}) {
    if (this.repaintBlocked === true || this.shape === null) {
      return;
    }

    if (this.svgPathString === null) {
      this.calculatePath();
    }

    JOSNUtil.ensureDefault(attributes, "path", this.svgPathString);

    super.repaint(attributes);
  }

  // 多边形碰撞检测
  hitTest(x, y) {
    const poly = this.getVertices().data;
    for (var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
      ((poly[i].y <= y && y < poly[j].y) ||
        (poly[j].y <= y && y < poly[i].y)) &&
        x <
        ((poly[j].x - poly[i].x) * (y - poly[i].y)) /
        (poly[j].y - poly[i].y) +
        poly[i].x &&
        (c = !c);
    return c;
  }

  /**
   * @inherit
   */
  getPersistentAttrs() {
    return extend(super.getPersistentAttrs(), {
      vertices: this.vertices.data.map(p => ({ x: p.x, y: p.y }))
    });
  }

  /**
   * @inherit
   */
  setPersistentAttrs(figure) {
    super.setPersistentAttrs(figure);

    if (typeof figure.vertices !== "undefined") {
      this.vertices = new ArrayList();
      figure.vertices.forEach(point => {
        this.addVertex(point);
      });
    }

    return this;
  }
}

namespace.shape.Polygon = Polygon;
